package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.spring.SpringUtils;
import com.ly.heart.domain.*;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.order.*;
import com.ly.heart.domain.king.procureRefund.FPURMRBENTRYBo;
import com.ly.heart.domain.king.procureRefund.FPURMRBFINBo;
import com.ly.heart.domain.king.procureRefund.ProcureRefundBo;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.service.IKingProcureRefundService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 采购退料单推送Service
 */
@Component
@Slf4j
public class KingProcureRefundPushService {

    private final SimpleDateFormat dateFormat = new SimpleDateFormat ( "yyyy-MM-dd" );

    @Resource
    private IKingProcureRefundService procureRefundService;
    @Resource
    private IKingOrgService iKingOrgService;

    /**
     * 公用金蝶推送方法
     * 合并保存，提交，审核三步
     * @param procureRefundId
     */
    @Transactional( rollbackFor = Exception.class )
    public void push(String procureRefundId){
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity>().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity::getIsDisabled, false ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        KingProcureRefundEntity kingProcureRefund = procureRefundService.selectKingProcureRefundEntityById(procureRefundId);
        if(Objects.isNull(kingProcureRefund)){
            throw new CustomException("采购退料单不存在！");
        }
        if(kingProcureRefund.getIsSend() == KingConstUtil.KING_DATA_IS_SEND_YES){
            throw new CustomException("该单据已推送金蝶,无需重复推送！");
        }
        try {
            K3CloudApi client = new K3CloudApi (identifyInfo);
            save(kingProcureRefund,client);
            submit(kingProcureRefund.getDocCode(),client);
            audit(kingProcureRefund.getDocCode(),client);
            updateSendSuccess(kingProcureRefund.getId());
            //调用即时库存
//            procureRefundService.updateRealTimeInventory(kingProcureRefund.getMaterialLists());
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("推送采购退料单失败！");
        }
    }

    /**
     * 修改推送状态
     * @param procureRefundId
     * @return
     */
    private void updateSendSuccess(String procureRefundId){
        KingProcureRefundEntity kingProcureRefund = new KingProcureRefundEntity();
        kingProcureRefund.setId(procureRefundId);
        kingProcureRefund.setIsSend(KingConstUtil.KING_DATA_IS_SEND_YES);
        kingProcureRefund.setUpdateTime(DateUtils.getNowDate());
        kingProcureRefund.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserId());
        boolean flag = procureRefundService.updateById(kingProcureRefund);
        if(!flag){
            throw new CustomException("修改推送状态失败！");
        }
    }


    /**
     * 金蝶-采购入库单保存
     * @param kingProcureRefund
     * @param client
     */
    public void save(KingProcureRefundEntity kingProcureRefund, K3CloudApi client){
        try{
            String formId = KingConstUtil.PUR_MRB;
            KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
            ProcureRefundBo procureRefundBo = this.assembleProcureRefund(kingProcureRefund);
            singleRequest.setModel(procureRefundBo);
            //调用接口
            String resultJson = client.save(formId, JSONObject.toJSONString(singleRequest));
            //用于记录结果
            Gson gson = new Gson();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("采购退料单推送成功: {}", gson.toJson(repoRet.getResult()));
                List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
                if(!CollectionUtils.isEmpty(successEntities)){
                    String docCode = successEntities.get(0).getNumber();
                    //修改为已推送状态
                    IKingProcureRefundService procureRefundService = SpringUtils.getBean(IKingProcureRefundService.class);
                    procureRefundService.update(new LambdaUpdateWrapper<KingProcureRefundEntity>().set(KingProcureRefundEntity::getIsSend,KingConstUtil.KING_DATA_IS_SEND_YES).eq(KingProcureRefundEntity::getDocCode,docCode));
                }
            } else {
                log.error("采购退料单推送失败: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 金蝶-采购入库单提交
     * @param docCode
     * @param client
     */
    public void submit(String docCode, K3CloudApi client){
        try{
            OrderSubmitBo submitBo = new OrderSubmitBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(docCode);
            submitBo.setNumbers(numbers);
            String formId = KingConstUtil.PUR_MRB;
            String resultJson = client.submit(formId, JSON.toJSONString ( submitBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("采购退料单提交成功: {}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("采购退料单提交失败: {}",gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 金蝶审核方法
     * @param docCode
     * @param client
     */
    public void audit(String docCode,K3CloudApi client){
        try{
            OrderAuditBo auditBo = new OrderAuditBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(docCode);
            auditBo.setNumbers(numbers);
            String formId = KingConstUtil.PUR_MRB;
            String resultJson = client.audit(formId,JSON.toJSONString ( auditBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("采购退料单审核成功:{}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("采购退料单审核失败:{}",gson.toJson(repoRet.getResult().getResponseStatus()) );
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }







    /**
     * 组装采购退料单推送金蝶对象
     * @param kingProcureRefund
     * @return
     */
    private ProcureRefundBo assembleProcureRefund(KingProcureRefundEntity kingProcureRefund){
        ProcureRefundBo procureRefundBo = new ProcureRefundBo();
        //单据类型
        FBillTypeIDBo FBillTypeID = new FBillTypeIDBo().setFNUMBER(kingProcureRefund.getDocType());
        procureRefundBo.setFBillTypeID(FBillTypeID);
        //业务类型
        procureRefundBo.setFBusinessType(kingProcureRefund.getDocBusinessType());
        //单据编号
        procureRefundBo.setFBillNo(kingProcureRefund.getDocCode());
        //退料日期
        procureRefundBo.setFDate(dateFormat.format(kingProcureRefund.getRefundTime()));
        //退料类型
        procureRefundBo.setFMRTYPE(kingProcureRefund.getRefundType());
        //退料方式
        procureRefundBo.setFMRMODE(kingProcureRefund.getRefundMethod());
        //退料组织 kingProcureRefund.getRefundOrg()
        BaseChildBo FStockOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        procureRefundBo.setFStockOrgId(FStockOrgId);
        //退料部门
        BaseChildBo FMRDeptId = new BaseChildBo().setFNumber(kingProcureRefund.getRefundDept());
        procureRefundBo.setFMRDeptId(FMRDeptId);
        //库存组
        BaseChildBo FSTOCKERGROUPID = new BaseChildBo().setFNumber(kingProcureRefund.getInventoryGroup());
        procureRefundBo.setFSTOCKERGROUPID(FSTOCKERGROUPID);
        //对应组织 kingProcureRefund.getRefundOrg()
        BaseChildBo FCorrespondOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        procureRefundBo.setFCorrespondOrgId(FCorrespondOrgId);
        //仓管员
        BaseChildBo FSTOCKERID = new BaseChildBo().setFNumber(kingProcureRefund.getManagementBy());
        procureRefundBo.setFSTOCKERID(FSTOCKERID);
        //退料原因
        BaseChildBo FMRREASON = new BaseChildBo().setFNumber(kingProcureRefund.getRefundReason());
        procureRefundBo.setFMRREASON(FMRREASON);
        //需求组织 kingProcureRefund.getRequireOrg()
        BaseChildBo FRequireOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        procureRefundBo.setFRequireOrgId(FRequireOrgId);
        //采购组织 kingProcureRefund.getPurchaseOrg()
        BaseChildBo FPurchaseOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        procureRefundBo.setFPurchaseOrgId(FPurchaseOrgId);
        //采购部门
        BaseChildBo FPURCHASEDEPTID = new BaseChildBo().setFNumber(kingProcureRefund.getPurchaseDept());
        procureRefundBo.setFPURCHASEDEPTID(FPURCHASEDEPTID);
        //采购组
        BaseChildBo FPURCHASERGROUPID = new BaseChildBo().setFNumber(kingProcureRefund.getPurchaseGroup());
        procureRefundBo.setFPURCHASERGROUPID(FPURCHASERGROUPID);
        //采购员
        BaseChildBo FPURCHASERID = new BaseChildBo().setFNumber(kingProcureRefund.getPurchaseBy());
        procureRefundBo.setFPURCHASERID(FPURCHASERID);
        //供应商 kingProcureRefund.getSupplierCode()
        BaseChildBo FSupplierID = new BaseChildBo().setFNumber("001");
        procureRefundBo.setFSupplierID(FSupplierID);
        //接收方
        BaseChildBo FACCEPTORID = new BaseChildBo().setFNumber(kingProcureRefund.getProviderCode());
        procureRefundBo.setFACCEPTORID(FACCEPTORID);
        //接收方地址
        procureRefundBo.setFAcceptAddress(kingProcureRefund.getProviderAddress());
        //结算方
        BaseChildBo FSettleId = new BaseChildBo().setFNumber(kingProcureRefund.getBalanceCode());
        procureRefundBo.setFSettleId(FSettleId);
        //收款方
        BaseChildBo FCHARGEID = new BaseChildBo().setFNumber(kingProcureRefund.getReceiveCode());
        procureRefundBo.setFCHARGEID(FCHARGEID);
        //货主类型
        procureRefundBo.setFOwnerTypeIdHead(kingProcureRefund.getCargoOwnerType());
        //货主
        BaseChildBo FOwnerIdHead = new BaseChildBo().setFNumber(kingProcureRefund.getCargoOwner());
        procureRefundBo.setFOwnerIdHead(FOwnerIdHead);
        //确认人
        FConfirmerIdBo FConfirmerId = new FConfirmerIdBo().setFUserID(kingProcureRefund.getConfirmName());
        procureRefundBo.setFConfirmerId(FConfirmerId);
        //确认日期
        if(Objects.nonNull(kingProcureRefund.getConfirmTime())){
            procureRefundBo.setFConfirmDate(dateFormat.format(kingProcureRefund.getConfirmTime()));
        }
        //接收方联系人
        FProviderContactIdBo FAcceptorContactID = new FProviderContactIdBo().setFCONTACTNUMBER(kingProcureRefund.getProviderContacts());
        procureRefundBo.setFAcceptorContactID(FAcceptorContactID);
        //邮箱
        procureRefundBo.setFAcceptEMail(kingProcureRefund.getEmail());
        //验收方式
        procureRefundBo.setFACCTYPE(kingProcureRefund.getCheckMethod());

        /*** 采购退料单财务信息 ***/
        FPURMRBFINBo FPURMRBFIN = new FPURMRBFINBo();
        //结算组织
        BaseChildBo FSettleOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        FPURMRBFIN.setFSettleOrgId(FSettleOrgId);
        //结算方式
        BaseChildBo FSETTLETYPEID = new BaseChildBo().setFNumber(kingProcureRefund.getSettlementMethod());
        FPURMRBFIN.setFSETTLETYPEID(FSETTLETYPEID);
        //结算币别
        BaseChildBo FSettleCurrId = new BaseChildBo().setFNumber(kingProcureRefund.getSettlementCurrency());
        FPURMRBFIN.setFSettleCurrId(FSettleCurrId);
        //付款条件
        BaseChildBo FPAYCONDITIONID = new BaseChildBo().setFNumber(kingProcureRefund.getTermOfPayment());
        FPURMRBFIN.setFPAYCONDITIONID(FPAYCONDITIONID);
        //含税
        FPURMRBFIN.setFIsIncludedTax(kingProcureRefund.getIsTax());
        //定价时点
        FPURMRBFIN.setFPRICETIMEPOINT(kingProcureRefund.getPricingTimePoint());
        //价目表
        BaseChildBo FPRICELISTID = new BaseChildBo().setFNumber(kingProcureRefund.getPriceInfoCode());
        FPURMRBFIN.setFPRICELISTID(FPRICELISTID);
        //折扣表
        BaseChildBo FDISCOUNTLISTID = new BaseChildBo().setFNumber(kingProcureRefund.getDiscountInfoCode());
        FPURMRBFIN.setFDISCOUNTLISTID(FDISCOUNTLISTID);
        //本位币
        BaseChildBo FLOCALCURRID = new BaseChildBo().setFNumber(kingProcureRefund.getBaseCurrency());
        FPURMRBFIN.setFLOCALCURRID(FLOCALCURRID);
        //汇率类型
        BaseChildBo FEXCHANGETYPEID = new BaseChildBo().setFNumber(kingProcureRefund.getExchangeRateType());
        FPURMRBFIN.setFEXCHANGETYPEID(FEXCHANGETYPEID);
        //汇率
        FPURMRBFIN.setFEXCHANGERATE(Integer.parseInt(kingProcureRefund.getExchangeRate()));
        //价外税
        FPURMRBFIN.setFISPRICEEXCLUDETAX(kingProcureRefund.getIsExtraPriceTax());
        procureRefundBo.setFPURMRBFIN(FPURMRBFIN);

        /*** 采购退料单物料明细信息 ***/
        List<FPURMRBENTRYBo> FPURMRBENTRY = new ArrayList<>();
        if(!CollectionUtils.isEmpty(kingProcureRefund.getMaterialLists())){
            List<KingProcureRefundMaterialEntity> materialLists = kingProcureRefund.getMaterialLists();
            for(KingProcureRefundMaterialEntity refundMaterial : materialLists){
                FPURMRBENTRYBo fpurmrbentryBo = new FPURMRBENTRYBo();
                //物料编码
                BaseChildBo FMATERIALID = new BaseChildBo().setFNumber(refundMaterial.getMaterialCode());
                fpurmrbentryBo.setFMATERIALID(FMATERIALID);
                //物料说明
 //               BaseChildBo FMaterialDesc = new BaseChildBo().setFNumber(refundMaterial.getM);
                //项目编号
                fpurmrbentryBo.setFProjectNo(refundMaterial.getProjectCode());
                //库存单位
                BaseChildBo FUnitID = new BaseChildBo().setFNumber(refundMaterial.getInventoryUnit());
                fpurmrbentryBo.setFUnitID(FUnitID);
                //实退数量
                fpurmrbentryBo.setFRMREALQTY(refundMaterial.getRefundNum());
                //补料数量
                fpurmrbentryBo.setFREPLENISHQTY(refundMaterial.getRepairNum());
                //扣款数量
                fpurmrbentryBo.setFKEAPAMTQTY(refundMaterial.getDeductionNum());
                //计价单位
                BaseChildBo FPRICEUNITID = new BaseChildBo().setFNumber(refundMaterial.getPricingUnit());
                fpurmrbentryBo.setFPRICEUNITID(FPRICEUNITID);
                //仓库 refundMaterial.getWarehouseCode()
                BaseChildBo FSTOCKID = new BaseChildBo().setFNumber("CK001");
                fpurmrbentryBo.setFSTOCKID(FSTOCKID);
                //仓位
                //库存状态 refundMaterial.getInventoryStatus()
                BaseChildBo FStockStatusId = new BaseChildBo().setFNumber("KCZT01_SYS");
                fpurmrbentryBo.setFStockStatusId(FStockStatusId);
                //备注
                fpurmrbentryBo.setFNOTE(refundMaterial.getRemark());
                //单价
                fpurmrbentryBo.setFPrice(refundMaterial.getPrice());
                //辅单位
                BaseChildBo FExtAuxUnitId = new BaseChildBo().setFNumber(refundMaterial.getAuxiliaryUnit());
                fpurmrbentryBo.setFExtAuxUnitId(FExtAuxUnitId);
                //实退数量(辅单位)
                fpurmrbentryBo.setFExtAuxUnitQty(refundMaterial.getRefundNumAuxiliary());
                //赠品
                fpurmrbentryBo.setFGiveAway(refundMaterial.getIsGiveaway());
                //计价基本数量
                fpurmrbentryBo.setFPriceBaseQty(refundMaterial.getPurchaseNumBase());
                //定价单位
                BaseChildBo FSetPriceUnitID = new BaseChildBo().setFNumber(refundMaterial.getFixedPricingUnit());
                fpurmrbentryBo.setFSetPriceUnitID(FSetPriceUnitID);
                //采购单位
                BaseChildBo FCarryUnitId = new BaseChildBo().setFNumber(refundMaterial.getPurchaseUnit());
                fpurmrbentryBo.setFCarryUnitId(FCarryUnitId);
                //供应商物料编码
                fpurmrbentryBo.setFSupMatId(refundMaterial.getSupplierMaterialCode());
                //供应商物料名称
                fpurmrbentryBo.setFSupMatName(refundMaterial.getSupplierMaterialName());
                //采购数量
                fpurmrbentryBo.setFCarryQty(refundMaterial.getPurchaseNum());
                //采购基本数量
                fpurmrbentryBo.setFCarryBaseQty(refundMaterial.getPricingNumBase());
                //应退数量
                fpurmrbentryBo.setFRMMUSTQTY(refundMaterial.getRefundedNum());
                //批号
//                BaseChildBo FLot = new BaseChildBo().setFNumber(refundMaterial.getBatchNum());
//                fpurmrbentryBo.setFLot(FLot);
                //辅助单位数量
                fpurmrbentryBo.setFAUXUNITQTY(refundMaterial.getAuxiliaryUnitNum());
                //货主类型
                fpurmrbentryBo.setFOWNERTYPEID(refundMaterial.getCargoOwnerType());
                //货主
                BaseChildBo FOWNERID = new BaseChildBo().setFNumber(refundMaterial.getCargoOwner());
                fpurmrbentryBo.setFOWNERID(FOWNERID);
                //税率
                fpurmrbentryBo.setFENTRYTAXRATE(refundMaterial.getTaxRate());
                //折扣率
                fpurmrbentryBo.setFDISCOUNTRATE(refundMaterial.getDiscountRate());
                //含税单价
                fpurmrbentryBo.setFTAXPRICE(refundMaterial.getContainsTaxPrice());

                KingProcureRefundMaterialDetailEntity materialDetailEntity = refundMaterial.getMaterialDetail();
                Optional.ofNullable(materialDetailEntity).ifPresent(materialDetail -> {
                    //需求跟踪号
                    fpurmrbentryBo.setFREQTRACENO(materialDetail.getRequireTrackingCode());
                    //已开票数量
                    fpurmrbentryBo.setFInvoicedJoinQty(Integer.parseInt(materialDetail.getInvoicedNum()));
                    //分录价目表
                    FBillTypeIDBo FPriceListEntry = new FBillTypeIDBo().setFNUMBER(materialDetail.getEntryPriceList());
                    fpurmrbentryBo.setFPriceListEntry(FPriceListEntry);
                    //bom版本
                    BaseChildBo FBOMID = new BaseChildBo().setFNumber(materialDetail.getBomVer());
                    fpurmrbentryBo.setFBOMID(FBOMID);
                    //供应商批号
                    fpurmrbentryBo.setFSupplierLot(materialDetail.getSupplierBatchNum());
                    //生产日期
                    fpurmrbentryBo.setFProduceDate(dateFormat.format(materialDetail.getManufactureTime()));
                    //到期日
                    fpurmrbentryBo.setFEXPIRYDATE(dateFormat.format(materialDetail.getValidTo()));
                    //单价折扣
                    fpurmrbentryBo.setFPriceDiscount(materialDetail.getPriceDiscount());
                    //费用项目
                    BaseChildBo FChargeProjectID = new BaseChildBo().setFNumber(materialDetail.getFeeInfoCode());
                    fpurmrbentryBo.setFChargeProjectID(FChargeProjectID);
                    //源单类型
                    fpurmrbentryBo.setFSRCBillTypeId(materialDetail.getSourceDocType());
                    //源单编号
                    fpurmrbentryBo.setFSRCBillNo(materialDetail.getSourceDocCode());
                    //计划跟踪号
                    fpurmrbentryBo.setFMtoNo(materialDetail.getPlanTrackingCode());

                });
                FPURMRBENTRY.add(fpurmrbentryBo);
            }
        }
        procureRefundBo.setFPURMRBENTRY(FPURMRBENTRY);
        return procureRefundBo;
    }











}
